/* 
 * Copyright (c) 2011-, Agilord Kft. - All Rights Reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.agilord.dragonflyp4;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Some basic utilities for handling the exif data returned by the JSON output
 * of exiftool
 * 
 * @author Istvan Soos
 * @since 1.0
 */
public class ExifUtils {

	public static String getStringValue(Map<String, Object> exif, String key) {
		String s = (String) exif.get(key);
		if (s != null) {
			s = s.trim();
			if (s.length() == 0)
				s = null;
		}
		return s;
	}

	public static Long getLongValue(Map<String, Object> exif, String key) {
		Long s = (Long) exif.get(key);
		return s;
	}

	public static String getLocation(Map<String, Object> exif) {
		String location = ExifUtils.getStringValue(exif, "Location");
		String city = ExifUtils.getStringValue(exif, "City");
		String state = ExifUtils.getStringValue(exif, "State");
		String country = ExifUtils.getStringValue(exif, "Country");

		StringBuilder sb = new StringBuilder();
		if (location != null && location.length() > 0)
			sb.append(location);

		if (city != null && city.length() > 0) {
			if (sb.length() > 0)
				sb.append(", ");
			sb.append(city);
		}

		if (state != null && state.length() > 0) {
			boolean append = true;
			if (city != null && city.length() > 0 && city.equals(state))
				append = false;
			if (append) {
				if (sb.length() > 0)
					sb.append(", ");
				sb.append(state);
			}
		}

		if (country != null && country.length() > 0) {
			if (sb.length() > 0)
				sb.append(", ");
			sb.append(country);
		}

		if (sb.length() > 0)
			return sb.toString();
		return null;
	}

	@SuppressWarnings("unchecked")
	public static List<String> getStringList(Map<String, Object> exif, String key) {
		Object o = exif.get(key);
		if (o == null)
			return null;
		if (o instanceof String) {
			LinkedList<String> x = new LinkedList<String>();
			x.add((String) o);
			return x;
		}
		return (List<String>) o;
	}

	public static String longer(String a, String b) {
		if (a == null)
			return b;
		if (b == null)
			return a;
		if (a.length() >= b.length())
			return a;
		return b;
	}

	public static String getTitle(Map<String, Object> exif) {
		String title = ExifUtils.getStringValue(exif, "Title");
		String headline = ExifUtils.getStringValue(exif, "Headline");

		title = longer(title, headline);
		return title;
	}

	public static void setTitle(ImageFile image, String title) {
		ProcessBuilder pb = new ProcessBuilder(
		        Configuration.get().getExiftool(),
		        "-overwrite_original_in_place",
		        "-Title=" + title,
		        "-Headline=" + title,
		        image.getFile().getAbsolutePath());
		try {
			pb.start().waitFor();
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}

		image.getExif().put("Title", title);
		image.getExif().put("Headline", title);
	}

	public static String getDescription(Map<String, Object> exif) {
		String descr = ExifUtils.getStringValue(exif, "Description");
		String ca = ExifUtils.getStringValue(exif, "Caption-Abstract");
		String id = ExifUtils.getStringValue(exif, "ImageDescription");

		descr = longer(descr, ca);
		descr = longer(descr, id);
		return descr;
	}

	public static void setDescription(ImageFile image, String description) {
		ProcessBuilder pb = new ProcessBuilder(
		        Configuration.get().getExiftool(),
		        "-overwrite_original_in_place",
		        "-Description=" + description,
		        "-Caption-Abstract=" + description,
		        "-ImageDescription=" + description,
		        image.getFile().getAbsolutePath());
		try {
			pb.start().waitFor();
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}

		image.getExif().put("Description", description);
		image.getExif().put("Caption-Abstract", description);
		image.getExif().put("ImageDescription", description);
	}

	public static void setKeywords(ImageFile image, Set<String> keys) {
		// check for nothing has changed
		List<String> list = getStringList(image.getExif(), "Keywords");
		Set<String> old = list == null ? new HashSet<String>() : new HashSet<String>(list);
		if (old.size() == keys.size()) {
			old.addAll(keys);
			if (old.size() == keys.size())
				return;
		}

		// write
		StringBuilder sb = new StringBuilder();
		for (String k : keys) {
			if (sb.length() > 0)
				sb.append(", ");
			sb.append(k);
		}
		String keywordText = sb.toString();

		if (keywordText.length() == 0)
			System.out.println("  ! - no keywords!?");

		// setting
		ProcessBuilder pb = new ProcessBuilder(
		        Configuration.get().getExiftool(),
		        "-overwrite_original_in_place",
		        "-sep", ", ", "-Keywords=" + keywordText,
		        image.getFile().getAbsolutePath());
		try {
			pb.start().waitFor();
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}

		image.getExif().put("Keywords", new ArrayList<String>(keys));
	}
}
